#!/usr/bin/env tclsh
# 本脚本用于调用iverilog实现 verilog仿真和查看波形
puts [pwd]

#exit 0
# 调用外部程序的过程
# cmd :指令
# args  :cmd后面跟的参数
proc exec_sys {cmd args} {
    set out [exec {*}[auto_execok $cmd] {*}$args]
    puts $out
}

#help
proc help {} {
    puts ""
    puts "快速仿真verilog的tcl脚本"
    puts "指令 -i  :初始化项目并生成模板"
    puts "指令     :仿真项目并打开波形"

}

# 创建tb.v文件，文件tb.v必须不存在
proc makeTbFile {} {
    set fileName "tb.v"
    if { [file exists $fileName] == 0 } { ;#文件不存在则创建文件
        set f [open tb.v w+]
        puts $f {`timescale 1ns / 1ps}
        puts $f {module tb ;}
        puts $f {reg clk,rst;}
        puts $f {}
        puts $f {//生成始时钟}
        puts $f {parameter NCLK = 4;}
        puts $f {initial begin}
        puts $f {	clk=0;}
        puts $f {	forever clk=#(NCLK/2) ~clk; }
        puts $f {end }
        puts $f {}
        puts $f {/****************** BEGIN ADD module inst ******************/}
        puts $f {}
        puts $f {/****************** BEGIN END module inst ******************/}
        puts $f {}
        puts $f {initial begin}
        puts $f {    $dumpfile("wave.lxt2");}
        puts $f {    $dumpvars(0, tb);   //dumpvars(深度, 实例化模块1，实例化模块2，.....)}
        puts $f {end}
        puts $f {}
        puts $f {initial begin}
        puts $f {   rst = 1;}
        puts $f {   #(NCLK) rst=0;}
        puts $f {   #(NCLK) rst=1; //复位信号}
        puts $f {}
        puts $f {	repeat(100) @(posedge clk)begin}
        puts $f {}
        puts $f {	end}
        puts $f {	$display("运行结束！");}
        puts $f {	$dumpflush;}
        puts $f {	$finish;}
        puts $f {	$stop;	}
        puts $f {end }
        puts $f {endmodule}
        close $f 
    } else {
        puts "tb.v 文件已存在!"
    }
}

# 参数处理
if { $argc == 1 } { ;#当输入的参数为1个的时候
    #根据参数决定接下来的操作
    set para [lindex $argv 0]
    if { [string equal $para "-i"] == 1 } { ;#初始化项目，生成仿真文件
        puts " -i 参数"
        # 创建tb.v文件
        makeTbFile
        exit 0 ;#退出脚本
    } elseif { [string equal $para "-r"] == 1} { ;#重新生成仿真文件
        puts " -r 参数"
        if { [file exists sim] == 1 && [file isdirectory sim] == 1} {
            #拷贝路径下所有.v文件到 sim
            set fileList [glob -nocomplain *.v] ;# 筛选出 .v 文件
            if { [llength $fileList] > 0 } {
                #拷贝所有的.v文件到sim目录下
                foreach i $fileList {
                    file copy -force $i sim
                }
            } else {
                puts "没有.v文件！"
                exit 0
            }
            #调用仿真工具
            cd sim
            #将编译文件写入 file.o 文件
            set f [open file.o w+]
            foreach i $fileList {
                puts $f $i
            }
            close $f
            exec_sys iverilog -o wave -f file.o ;#编译
            exec_sys vvp -n wave -lxt2 &;#仿真        
        } else {
            puts "不存在仿真文件路径 sim!"
        }
        exit 0
    }
}
# 执行仿真功能，并打开波形显示
if { $argc == 0 } {
    if { [file exists sim ] == 0 } {
        #创建 sim 文件夹
        file mkdir sim
    } else {
        #删除sim下的所有文件
        set fileList [glob -nocomplain sim/*]
        puts $fileList
        file delete $fileList
    }
    #拷贝路径下所有.v文件到 sim
    set fileList [glob -nocomplain *.v] ;# 筛选出 .v 文件
    if { [llength $fileList] > 0 } {
        #拷贝所有的.v文件到sim目录下
        foreach i $fileList {
            file copy -force $i sim
        }
    } else {
        puts "没有.v文件！"
        exit 0
    }
    #调用仿真工具
    cd sim
    #将编译文件写入 file.o 文件
    set f [open file.o w+]
    foreach i $fileList {
        puts $f $i
    }
    close $f
    exec_sys iverilog -o wave -f file.o ;#编译
    exec_sys vvp -n wave -lxt2 ;#仿真
    exec_sys gtkwave wave.lxt2 ;#显示波形
	puts "ok"
}






